
<!doctype html>
<html lang="en" class="no-js">
  <head>
    
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width,initial-scale=1">
      
        <meta name="description" content="ESP8266/ESP32 WLAN configuration at run time with web interface">
      
      
        <meta name="author" content="Hieromon Ikasamo">
      
      
        <link rel="canonical" href="https://Hieromon.github.io/AutoConnect/acupload.html">
      
      
        <link rel="prev" href="credit.html">
      
      
        <link rel="next" href="colorized.html">
      
      <link rel="icon" href="assets/images/favicon.png">
      <meta name="generator" content="mkdocs-1.4.2, mkdocs-material-9.0.9">
    
    
      
        <title>File upload handler - AutoConnect for ESP8266/ESP32</title>
      
    
    
      <link rel="stylesheet" href="assets/stylesheets/main.0d440cfe.min.css">
      
        
        <link rel="stylesheet" href="assets/stylesheets/palette.2505c338.min.css">
      
      

    
    
    
      
        
        
        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
      
    
    
      <link rel="stylesheet" href="css/paragraph.css">
    
      <link rel="stylesheet" href="css/extra.css">
    
      <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.14.0/css/all.css">
    
    <script>__md_scope=new URL(".",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
    
      
  


  
  


  <script id="__analytics">function __md_analytics(){function n(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],n("js",new Date),n("config","G-EHK8XV10VE"),document.addEventListener("DOMContentLoaded",function(){document.forms.search&&document.forms.search.query.addEventListener("blur",function(){this.value&&n("event","search",{search_term:this.value})}),document$.subscribe(function(){var a=document.forms.feedback;if(void 0!==a)for(var e of a.querySelectorAll("[type=submit]"))e.addEventListener("click",function(e){e.preventDefault();var t=document.location.pathname,e=this.getAttribute("data-md-value");n("event","feedback",{page:t,data:e}),a.firstElementChild.disabled=!0;e=a.querySelector(".md-feedback__note [data-md-value='"+e+"']");e&&(e.hidden=!1)}),a.hidden=!1}),location$.subscribe(function(e){n("config","G-EHK8XV10VE",{page_path:e.pathname})})});var e=document.createElement("script");e.async=!0,e.src="https://www.googletagmanager.com/gtag/js?id=G-EHK8XV10VE",document.getElementById("__analytics").insertAdjacentElement("afterEnd",e)}</script>

  
    <script>"undefined"!=typeof __md_analytics&&__md_analytics()</script>
  

    
    
    
  </head>
  
  
    
    
    
    
    
    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo">
  
    
    
    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
    <label class="md-overlay" for="__drawer"></label>
    <div data-md-component="skip">
      
        
        <a href="#uploading-file-from-web-browser" class="md-skip">
          Skip to content
        </a>
      
    </div>
    <div data-md-component="announce">
      
    </div>
    
    
      

<header class="md-header" data-md-component="header">
  <nav class="md-header__inner md-grid" aria-label="Header">
    <a href="index.html" title="AutoConnect for ESP8266/ESP32" class="md-header__button md-logo" aria-label="AutoConnect for ESP8266/ESP32" data-md-component="logo">
      
  <img src="images/arduino-logo.svg" alt="logo">

    </a>
    <label class="md-header__button md-icon" for="__drawer">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
    </label>
    <div class="md-header__title" data-md-component="header-title">
      <div class="md-header__ellipsis">
        <div class="md-header__topic">
          <span class="md-ellipsis">
            AutoConnect for ESP8266/ESP32
          </span>
        </div>
        <div class="md-header__topic" data-md-component="header-topic">
          <span class="md-ellipsis">
            
              File upload handler
            
          </span>
        </div>
      </div>
    </div>
    
    
    
      <label class="md-header__button md-icon" for="__search">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
      </label>
      <div class="md-search" data-md-component="search" role="dialog">
  <label class="md-search__overlay" for="__search"></label>
  <div class="md-search__inner" role="search">
    <form class="md-search__form" name="search">
      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
      <label class="md-search__icon md-icon" for="__search">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
      </label>
      <nav class="md-search__options" aria-label="Search">
        
        <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
        </button>
      </nav>
      
    </form>
    <div class="md-search__output">
      <div class="md-search__scrollwrap" data-md-scrollfix>
        <div class="md-search-result" data-md-component="search-result">
          <div class="md-search-result__meta">
            Initializing search
          </div>
          <ol class="md-search-result__list" role="presentation"></ol>
        </div>
      </div>
    </div>
  </div>
</div>
    
    
      <div class="md-header__source">
        <a href="https://github.com/Hieromon/AutoConnect" title="Go to repository" class="md-source" data-md-component="source">
  <div class="md-source__icon md-icon">
    
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
  </div>
  <div class="md-source__repository">
    Hieromon/AutoConnect
  </div>
</a>
      </div>
    
  </nav>
  
</header>
    
    <div class="md-container" data-md-component="container">
      
      
        
          
        
      
      <main class="md-main" data-md-component="main">
        <div class="md-main__inner md-grid">
          
            
              
              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
                <div class="md-sidebar__scrollwrap">
                  <div class="md-sidebar__inner">
                    


<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
  <label class="md-nav__title" for="__drawer">
    <a href="index.html" title="AutoConnect for ESP8266/ESP32" class="md-nav__button md-logo" aria-label="AutoConnect for ESP8266/ESP32" data-md-component="logo">
      
  <img src="images/arduino-logo.svg" alt="logo">

    </a>
    AutoConnect for ESP8266/ESP32
  </label>
  
    <div class="md-nav__source">
      <a href="https://github.com/Hieromon/AutoConnect" title="Go to repository" class="md-source" data-md-component="source">
  <div class="md-source__icon md-icon">
    
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
  </div>
  <div class="md-source__repository">
    Hieromon/AutoConnect
  </div>
</a>
    </div>
  
  <ul class="md-nav__list" data-md-scrollfix>
    
      
      
      

  
  
  
    <li class="md-nav__item">
      <a href="index.html" class="md-nav__link">
        Overview
      </a>
    </li>
  

    
      
      
      

  
  
  
    <li class="md-nav__item">
      <a href="gettingstarted.html" class="md-nav__link">
        Getting started
      </a>
    </li>
  

    
      
      
      

  
  
  
    <li class="md-nav__item">
      <a href="menu.html" class="md-nav__link">
        AutoConnect menu
      </a>
    </li>
  

    
      
      
      

  
  
  
    <li class="md-nav__item">
      <a href="basicusage.html" class="md-nav__link">
        Basic usage
      </a>
    </li>
  

    
      
      
      

  
  
  
    
    <li class="md-nav__item md-nav__item--nested">
      
      
      
      
      <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
      
      
      
        <label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
          Advanced usage
          <span class="md-nav__icon md-icon"></span>
        </label>
      
      <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
        <label class="md-nav__title" for="__nav_5">
          <span class="md-nav__icon md-icon"></span>
          Advanced usage
        </label>
        <ul class="md-nav__list" data-md-scrollfix>
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="advancedusage.html" class="md-nav__link">
        Advanced usage
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="adconnection.html" class="md-nav__link">
        AutoConnect WiFi connection control
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="adcpcontrol.html" class="md-nav__link">
        Captive portal control
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="adnetwork.html" class="md-nav__link">
        Settings and controls for network and WiFi
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="adauthentication.html" class="md-nav__link">
        Authentication settings
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="adcredential.html" class="md-nav__link">
        Credential accesses
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="adexterior.html" class="md-nav__link">
        Customizing page appearance
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="adothers.html" class="md-nav__link">
        Other operation settings and controls
      </a>
    </li>
  

            
          
        </ul>
      </nav>
    </li>
  

    
      
      
      

  
  
  
    
    <li class="md-nav__item md-nav__item--nested">
      
      
      
      
      <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6" >
      
      
      
        <label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0">
          Custom Web pages
          <span class="md-nav__icon md-icon"></span>
        </label>
      
      <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
        <label class="md-nav__title" for="__nav_6">
          <span class="md-nav__icon md-icon"></span>
          Custom Web pages
        </label>
        <ul class="md-nav__list" data-md-scrollfix>
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="acintro.html" class="md-nav__link">
        Custom Web pages with AutoConnect
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="acelements.html" class="md-nav__link">
        AutoConnectElements
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="acjson.html" class="md-nav__link">
        Custom Web pages with JSON
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="achandling.html" class="md-nav__link">
        Handling the custom Web pages
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="acinteract.html" class="md-nav__link">
        Interact between Sketch and AutoConnectElements
      </a>
    </li>
  

            
          
        </ul>
      </nav>
    </li>
  

    
      
      
      

  
  
  
    
    <li class="md-nav__item md-nav__item--nested">
      
      
      
      
      <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7" >
      
      
      
        <label class="md-nav__link" for="__nav_7" id="__nav_7_label" tabindex="0">
          OTA Updates
          <span class="md-nav__icon md-icon"></span>
        </label>
      
      <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false">
        <label class="md-nav__title" for="__nav_7">
          <span class="md-nav__icon md-icon"></span>
          OTA Updates
        </label>
        <ul class="md-nav__list" data-md-scrollfix>
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="otaupdate.html" class="md-nav__link">
        OTA Updates
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="otabrowser.html" class="md-nav__link">
        OTA via Web Browser
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="otaserver.html" class="md-nav__link">
        OTA using Update Server
      </a>
    </li>
  

            
          
        </ul>
      </nav>
    </li>
  

    
      
      
      

  
  
  
    <li class="md-nav__item">
      <a href="filesystem.html" class="md-nav__link">
        Using Filesystem
      </a>
    </li>
  

    
      
      
      

  
  
  
    
    <li class="md-nav__item md-nav__item--nested">
      
      
      
      
      <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_9" >
      
      
      
        <label class="md-nav__link" for="__nav_9" id="__nav_9_label" tabindex="0">
          Library APIs
          <span class="md-nav__icon md-icon"></span>
        </label>
      
      <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_9_label" aria-expanded="false">
        <label class="md-nav__title" for="__nav_9">
          <span class="md-nav__icon md-icon"></span>
          Library APIs
        </label>
        <ul class="md-nav__list" data-md-scrollfix>
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="api.html" class="md-nav__link">
        AutoConnect API
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="apiaux.html" class="md-nav__link">
        AutoConnectAux API
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="apiconfig.html" class="md-nav__link">
        AutoConnectConfig API
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="apielements.html" class="md-nav__link">
        AutoConnectElements API
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="apiupdate.html" class="md-nav__link">
        AutoConnectUpdate API
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="apiextra.html" class="md-nav__link">
        Something extra
      </a>
    </li>
  

            
          
        </ul>
      </nav>
    </li>
  

    
      
      
      

  
  
  
    
    <li class="md-nav__item md-nav__item--nested">
      
      
      
      
      <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_10" >
      
      
      
        <label class="md-nav__link" for="__nav_10" id="__nav_10_label" tabindex="0">
          Examples
          <span class="md-nav__icon md-icon"></span>
        </label>
      
      <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_10_label" aria-expanded="false">
        <label class="md-nav__title" for="__nav_10">
          <span class="md-nav__icon md-icon"></span>
          Examples
        </label>
        <ul class="md-nav__list" data-md-scrollfix>
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="howtoembed.html" class="md-nav__link">
        How to embed
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="datatips.html" class="md-nav__link">
        Tips for data conversion
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="menuize.html" class="md-nav__link">
        Attach the menus
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="wojson.html" class="md-nav__link">
        Custom Web pages w/o JSON
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="esp32cam.html" class="md-nav__link">
        Works with ESP32-CAM
      </a>
    </li>
  

            
          
        </ul>
      </nav>
    </li>
  

    
      
      
      

  
  
    
  
  
    
    <li class="md-nav__item md-nav__item--active md-nav__item--nested">
      
      
      
      
      <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_11" checked>
      
      
      
        <label class="md-nav__link" for="__nav_11" id="__nav_11_label" tabindex="0">
          Appendix
          <span class="md-nav__icon md-icon"></span>
        </label>
      
      <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_11_label" aria-expanded="true">
        <label class="md-nav__title" for="__nav_11">
          <span class="md-nav__icon md-icon"></span>
          Appendix
        </label>
        <ul class="md-nav__list" data-md-scrollfix>
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="lsbegin.html" class="md-nav__link">
        Inside AutoConnect::begin
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="credit.html" class="md-nav__link">
        Saved credentials access
      </a>
    </li>
  

            
          
            
              
  
  
    
  
  
    <li class="md-nav__item md-nav__item--active">
      
      <input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
      
      
      
        <label class="md-nav__link md-nav__link--active" for="__toc">
          File upload handler
          <span class="md-nav__icon md-icon"></span>
        </label>
      
      <a href="acupload.html" class="md-nav__link md-nav__link--active">
        File upload handler
      </a>
      
        

<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
  
  
  
  
    <label class="md-nav__title" for="__toc">
      <span class="md-nav__icon md-icon"></span>
      Table of contents
    </label>
    <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
      
        <li class="md-nav__item">
  <a href="#uploading-file-from-web-browser" class="md-nav__link">
    Uploading file from Web Browser
  </a>
  
</li>
      
        <li class="md-nav__item">
  <a href="#basic-steps-of-the-file-upload-sketch" class="md-nav__link">
    Basic steps of the file upload sketch
  </a>
  
</li>
      
        <li class="md-nav__item">
  <a href="#where-will-the-file-upload" class="md-nav__link">
    Where will the file upload
  </a>
  
</li>
      
        <li class="md-nav__item">
  <a href="#when-it-will-be-uploaded" class="md-nav__link">
    When it will be uploaded
  </a>
  
</li>
      
        <li class="md-nav__item">
  <a href="#the-file-name-for-the-uploaded-file" class="md-nav__link">
    The file name for the uploaded file
  </a>
  
</li>
      
        <li class="md-nav__item">
  <a href="#upload-to-a-device-other-than-flash-or-sd" class="md-nav__link">
    Upload to a device other than Flash or SD
  </a>
  
    <nav class="md-nav" aria-label="Upload to a device other than Flash or SD">
      <ul class="md-nav__list">
        
          <li class="md-nav__item">
  <a href="#upload-handler-base-class" class="md-nav__link">
     Upload handler base class
  </a>
  
    <nav class="md-nav" aria-label=" Upload handler base class">
      <ul class="md-nav__list">
        
          <li class="md-nav__item">
  <a href="#constructor" class="md-nav__link">
     Constructor
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#member-functions" class="md-nav__link">
     Member functions
  </a>
  
</li>
        
      </ul>
    </nav>
  
</li>
        
          <li class="md-nav__item">
  <a href="#register-custom-upload-handler" class="md-nav__link">
     Register custom upload handler
  </a>
  
</li>
        
      </ul>
    </nav>
  
</li>
      
    </ul>
  
</nav>
      
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="colorized.html" class="md-nav__link">
        Custom colorized
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="changelabel.html" class="md-nav__link">
        Change label text
      </a>
    </li>
  

            
          
        </ul>
      </nav>
    </li>
  

    
      
      
      

  
  
  
    <li class="md-nav__item">
      <a href="faq.html" class="md-nav__link">
        FAQ
      </a>
    </li>
  

    
      
      
      

  
  
  
    <li class="md-nav__item">
      <a href="changelog.html" class="md-nav__link">
        Change log
      </a>
    </li>
  

    
      
      
      

  
  
  
    <li class="md-nav__item">
      <a href="license.html" class="md-nav__link">
        License
      </a>
    </li>
  

    
  </ul>
</nav>
                  </div>
                </div>
              </div>
            
            
              
              <div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
                <div class="md-sidebar__scrollwrap">
                  <div class="md-sidebar__inner">
                    

<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
  
  
  
  
    <label class="md-nav__title" for="__toc">
      <span class="md-nav__icon md-icon"></span>
      Table of contents
    </label>
    <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
      
        <li class="md-nav__item">
  <a href="#uploading-file-from-web-browser" class="md-nav__link">
    Uploading file from Web Browser
  </a>
  
</li>
      
        <li class="md-nav__item">
  <a href="#basic-steps-of-the-file-upload-sketch" class="md-nav__link">
    Basic steps of the file upload sketch
  </a>
  
</li>
      
        <li class="md-nav__item">
  <a href="#where-will-the-file-upload" class="md-nav__link">
    Where will the file upload
  </a>
  
</li>
      
        <li class="md-nav__item">
  <a href="#when-it-will-be-uploaded" class="md-nav__link">
    When it will be uploaded
  </a>
  
</li>
      
        <li class="md-nav__item">
  <a href="#the-file-name-for-the-uploaded-file" class="md-nav__link">
    The file name for the uploaded file
  </a>
  
</li>
      
        <li class="md-nav__item">
  <a href="#upload-to-a-device-other-than-flash-or-sd" class="md-nav__link">
    Upload to a device other than Flash or SD
  </a>
  
    <nav class="md-nav" aria-label="Upload to a device other than Flash or SD">
      <ul class="md-nav__list">
        
          <li class="md-nav__item">
  <a href="#upload-handler-base-class" class="md-nav__link">
     Upload handler base class
  </a>
  
    <nav class="md-nav" aria-label=" Upload handler base class">
      <ul class="md-nav__list">
        
          <li class="md-nav__item">
  <a href="#constructor" class="md-nav__link">
     Constructor
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#member-functions" class="md-nav__link">
     Member functions
  </a>
  
</li>
        
      </ul>
    </nav>
  
</li>
        
          <li class="md-nav__item">
  <a href="#register-custom-upload-handler" class="md-nav__link">
     Register custom upload handler
  </a>
  
</li>
        
      </ul>
    </nav>
  
</li>
      
    </ul>
  
</nav>
                  </div>
                </div>
              </div>
            
          
          
            <div class="md-content" data-md-component="content">
              <article class="md-content__inner md-typeset">
                
                  



  <h1>File upload handler</h1>

<h2 id="uploading-file-from-web-browser">Uploading file from Web Browser<a class="headerlink" href="#uploading-file-from-web-browser" title="Permanent link">&para;</a></h2>
<p>If you have to write some data individually to the ESP8266/ESP32 module for the Sketch behavior, the <a href="acelements.html#autoconnectfile">AutoConnectFile</a> element will assist with your wants implementation. The AutoConnectFile element produces an HTML <code>&lt;input type="file"&gt;</code> tag and can save uploaded file to the flash or external SD of the ESP8266/ESP32 module. The handler for saving is built into AutoConnect. You can use it to inject any sketch data such as the initial values for the custom Web page into the ESP module via OTA without using the Sketch data upload tool of Arduino-IDE.</p>
<p style="display:block;margin-left:auto;margin-right:auto;width:603px;height:368px;border:1px solid lightgray;"><img data-gifffer="images/upload.gif" data-gifffer-width="601" data-gifffer-height="366""/></p>

<h2 id="basic-steps-of-the-file-upload-sketch">Basic steps of the file upload sketch<a class="headerlink" href="#basic-steps-of-the-file-upload-sketch" title="Permanent link">&para;</a></h2>
<p>Here is the basic procedure of the Sketch which can upload files from the client browser using AutoConnectFile:<sup id="fnref:1"><a class="footnote-ref" href="#fn:1">1</a></sup></p>
<ol>
<li>Place AutoConnectFile on a custom Web page by writing JSON or constructor code directly with the Sketch.</li>
<li>Place other AutoConnectElements as needed.</li>
<li>Place AutoConnectSubmit on the same custom Web page.</li>
<li>Perform the following process in the on-handler of submitting destination:<ul>
<li>Retrieve the <a href="apielements.html#autoconnectfile">AutoConnectFile instance</a> from the custom Web page where you placed the AutoConnectFile element using the <a href="apiaux.html#getelement">AutoConnectAux::getElement</a> function or the <a href="apiaux.html#operator">operator []</a>.</li>
<li>Start access to the device specified as the upload destination. In usually, it depends on the file system's begin function. For example, if you specified Flash's SPIFFS as the upload destination, invokes <em>SPIFFS.begin()</em>.</li>
<li>The <a href="acelements.html#value_3">value member</a> of AutoConnectFile contains the file name of the upload file. Use its file name to access the uploaded file on the device.</li>
<li>Invokes the end function associated with the begin to close the device. It is the <em>SPIFFS.end()*</em> if the flash on the ESP module has been begun for SPIFFS.</li>
</ul>
</li>
</ol>
<p>The following sketch is an example that implements the above basic steps. The <em>postUpload</em> function is the on-handler and retrieves the AutoConnectFile as named <code>upload_file</code>. You should note that this handler is <strong>not</strong> for a custom Web page placed with its AutoConnectFile element. The uploaded file should be processed by the handler for the transition destination page from the AutoConnectFile element placed page. AutoConnect built-in upload handler will save the uploaded file to the specified device before invoking the <em>postUpload</em> function.</p>
<p>However, If you use uploaded files in different situations, it may be more appropriate to place the actual handling process outside the handler. It applies for the parameter file, etc. The important thing is that you do not have to sketch file reception and storing logic by using the AutoConnectFile element and the upload handler built into the AutoConnect.</p>
<div class="highlight" style="background: #272822"><pre style="line-height: 125%;"><span></span><code><span style="color: #75715e">#include</span><span style="color: #f8f8f2"> </span><span style="color: #75715e">&lt;ESP8266WiFi.h&gt;</span>
<span style="color: #75715e">#include</span><span style="color: #f8f8f2"> </span><span style="color: #75715e">&lt;ESP8266WebServer.h&gt;</span>
<span style="color: #75715e">#include</span><span style="color: #f8f8f2"> </span><span style="color: #75715e">&lt;FS.h&gt;</span>
<span style="color: #75715e">#include</span><span style="color: #f8f8f2"> </span><span style="color: #75715e">&lt;AutoConnect.h&gt;</span>

<span style="color: #75715e">// Upload request custom Web page</span>
<span style="color: #66d9ef">static</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">char</span><span style="color: #f8f8f2"> PAGE_UPLOAD[] PROGMEM </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> </span><span style="color: #e6db74">R&quot;(</span>
<span style="color: #e6db74">{</span>
<span style="color: #e6db74">  &quot;uri&quot;: &quot;/&quot;,</span>
<span style="color: #e6db74">  &quot;title&quot;: &quot;Upload&quot;,</span>
<span style="color: #e6db74">  &quot;menu&quot;: true,</span>
<span style="color: #e6db74">  &quot;element&quot;: [</span>
<span style="color: #e6db74">    { &quot;name&quot;:&quot;caption&quot;, &quot;type&quot;:&quot;ACText&quot;, &quot;value&quot;:&quot;&lt;h2&gt;File uploading platform&lt;h2&gt;&quot; },</span>
<span style="background-color: #49483e"><span style="color: #e6db74">    { &quot;name&quot;:&quot;upload_file&quot;, &quot;type&quot;:&quot;ACFile&quot;, &quot;label&quot;:&quot;Select file: &quot;, &quot;store&quot;:&quot;fs&quot; },</span>
</span><span style="color: #e6db74">    { &quot;name&quot;:&quot;upload&quot;, &quot;type&quot;:&quot;ACSubmit&quot;, &quot;value&quot;:&quot;UPLOAD&quot;, &quot;uri&quot;:&quot;/upload&quot; }</span>
<span style="color: #e6db74">  ]</span>
<span style="color: #e6db74">}</span>
<span style="color: #e6db74">)&quot;</span><span style="color: #f8f8f2">;</span>

<span style="color: #75715e">// Upload result display</span>
<span style="color: #66d9ef">static</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">char</span><span style="color: #f8f8f2"> PAGE_BROWSE[] PROGMEM </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> </span><span style="color: #e6db74">R&quot;(</span>
<span style="color: #e6db74">{</span>
<span style="color: #e6db74">  &quot;uri&quot;: &quot;/upload&quot;,</span>
<span style="color: #e6db74">  &quot;title&quot;: &quot;Upload&quot;,</span>
<span style="color: #e6db74">  &quot;menu&quot;: false,</span>
<span style="color: #e6db74">  &quot;element&quot;: [</span>
<span style="color: #e6db74">    { &quot;name&quot;:&quot;caption&quot;, &quot;type&quot;:&quot;ACText&quot;, &quot;value&quot;:&quot;&lt;h2&gt;Uploading ended&lt;h2&gt;&quot; },</span>
<span style="color: #e6db74">    { &quot;name&quot;:&quot;filename&quot;, &quot;type&quot;:&quot;ACText&quot; },</span>
<span style="color: #e6db74">    { &quot;name&quot;:&quot;size&quot;, &quot;type&quot;:&quot;ACText&quot;, &quot;format&quot;:&quot;%s bytes uploaded&quot; },</span>
<span style="color: #e6db74">    { &quot;name&quot;:&quot;content_type&quot;, &quot;type&quot;:&quot;ACText&quot;, &quot;format&quot;:&quot;Content: %s&quot; }</span>
<span style="color: #e6db74">  ]</span>
<span style="color: #e6db74">}</span>
<span style="color: #e6db74">)&quot;</span><span style="color: #f8f8f2">;</span>

<span style="color: #f8f8f2">ESP8266WebServer server;</span>
<span style="color: #f8f8f2">AutoConnect </span><span style="color: #a6e22e">portal</span><span style="color: #f8f8f2">(server);</span>
<span style="color: #75715e">// Declare AutoConnectAux separately as a custom web page to access</span>
<span style="color: #75715e">// easily for each page in the post-upload handler.</span>
<span style="color: #f8f8f2">AutoConnectAux auxUpload;</span>
<span style="color: #f8f8f2">AutoConnectAux auxBrowse;</span>

<span style="color: #75715e">/**</span>
<span style="color: #75715e"> * Post uploading, AutoConnectFile&#39;s built-in upload handler reads the</span>
<span style="color: #75715e"> * file saved in SPIFFS and displays the file contents on /upload custom</span>
<span style="color: #75715e"> * web page. However, only files with mime type uploaded as text are</span>
<span style="color: #75715e"> * displayed. A custom web page handler is called after upload.</span>
<span style="color: #75715e"> * @param  aux  AutoConnectAux(/upload)</span>
<span style="color: #75715e"> * @param  args PageArgument</span>
<span style="color: #75715e"> * @return Uploaded text content</span>
<span style="color: #75715e"> */</span>
<span style="color: #f8f8f2">String </span><span style="color: #a6e22e">postUpload</span><span style="color: #f8f8f2">(AutoConnectAux</span><span style="color: #f92672">&amp;</span><span style="color: #f8f8f2"> aux, PageArgument</span><span style="color: #f92672">&amp;</span><span style="color: #f8f8f2"> args) {</span>
<span style="color: #f8f8f2">  String  content;</span>
<span style="background-color: #49483e"><span style="color: #f8f8f2">  AutoConnectFile</span><span style="color: #f92672">&amp;</span><span style="color: #f8f8f2">  upload </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> auxUpload[</span><span style="color: #e6db74">&quot;upload_file&quot;</span><span style="color: #f8f8f2">].as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectFile</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">();</span>
</span><span style="color: #f8f8f2">  AutoConnectText</span><span style="color: #f92672">&amp;</span><span style="color: #f8f8f2">  aux_filename </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> aux[</span><span style="color: #e6db74">&quot;filename&quot;</span><span style="color: #f8f8f2">].as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">();</span>
<span style="color: #f8f8f2">  AutoConnectText</span><span style="color: #f92672">&amp;</span><span style="color: #f8f8f2">  aux_size </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> aux[</span><span style="color: #e6db74">&quot;size&quot;</span><span style="color: #f8f8f2">].as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">();</span>
<span style="color: #f8f8f2">  AutoConnectText</span><span style="color: #f92672">&amp;</span><span style="color: #f8f8f2">  aux_contentType </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> aux[</span><span style="color: #e6db74">&quot;content_type&quot;</span><span style="color: #f8f8f2">].as</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">AutoConnectText</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">();</span>
<span style="color: #f8f8f2">  </span><span style="color: #75715e">// Assignment operator can be used for the element attribute.</span>
<span style="color: #f8f8f2">  aux_filename.value </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> upload.value;</span>
<span style="color: #f8f8f2">  aux_size.value </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> String(upload.size);</span>
<span style="color: #f8f8f2">  aux_contentType.value </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> upload.mimeType;</span>
<span style="color: #f8f8f2">  </span><span style="color: #75715e">// The file saved by the AutoConnect upload handler is read from</span>
<span style="color: #f8f8f2">  </span><span style="color: #75715e">// the EEPROM and echoed to a custom web page.</span>
<span style="color: #f8f8f2">  SPIFFS.begin();</span>
<span style="background-color: #49483e"><span style="color: #f8f8f2">  File uploadFile </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> SPIFFS.open(String(</span><span style="color: #e6db74">&quot;/&quot;</span><span style="color: #f8f8f2"> </span><span style="color: #f92672">+</span><span style="color: #f8f8f2"> upload.value).c_str(), </span><span style="color: #e6db74">&quot;r&quot;</span><span style="color: #f8f8f2">);</span>
</span><span style="color: #f8f8f2">  </span><span style="color: #66d9ef">if</span><span style="color: #f8f8f2"> (uploadFile) {</span>
<span style="color: #f8f8f2">    </span><span style="color: #66d9ef">while</span><span style="color: #f8f8f2"> (uploadFile.available()) {</span>
<span style="background-color: #49483e"><span style="color: #f8f8f2">      </span><span style="color: #66d9ef">char</span><span style="color: #f8f8f2"> c </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> uploadFile.read();</span>
</span><span style="color: #f8f8f2">      Serial.print(c);</span>
<span style="color: #f8f8f2">    }</span>
<span style="background-color: #49483e"><span style="color: #f8f8f2">    uploadFile.close();</span>
</span><span style="color: #f8f8f2">  }</span>
<span style="color: #f8f8f2">  </span><span style="color: #66d9ef">else</span>
<span style="color: #f8f8f2">    content </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> </span><span style="color: #e6db74">&quot;Not saved&quot;</span><span style="color: #f8f8f2">;</span>
<span style="color: #f8f8f2">  SPIFFS.end();</span>
<span style="color: #f8f8f2">  </span><span style="color: #66d9ef">return</span><span style="color: #f8f8f2"> String();</span>
<span style="color: #f8f8f2">}</span>

<span style="color: #66d9ef">void</span><span style="color: #f8f8f2"> </span><span style="color: #a6e22e">setup</span><span style="color: #f8f8f2">() {</span>
<span style="color: #f8f8f2">  delay(</span><span style="color: #ae81ff">1000</span><span style="color: #f8f8f2">);</span>
<span style="color: #f8f8f2">  Serial.begin(</span><span style="color: #ae81ff">115200</span><span style="color: #f8f8f2">);</span>
<span style="color: #f8f8f2">  Serial.println();</span>

<span style="color: #f8f8f2">  auxUpload.load(PAGE_UPLOAD);</span>
<span style="color: #f8f8f2">  auxBrowse.load(PAGE_BROWSE);</span>
<span style="color: #f8f8f2">  portal.join({ auxUpload, auxBrowse });</span>
<span style="background-color: #49483e"><span style="color: #f8f8f2">  auxBrowse.on(postUpload);</span>
</span><span style="color: #f8f8f2">  portal.begin();</span>
<span style="color: #f8f8f2">}</span>

<span style="color: #66d9ef">void</span><span style="color: #f8f8f2"> </span><span style="color: #a6e22e">loop</span><span style="color: #f8f8f2">() {</span>
<span style="color: #f8f8f2">  portal.handleClient();</span>
<span style="color: #f8f8f2">}</span>
</code></pre></div>
<h2 id="where-will-the-file-upload">Where will the file upload<a class="headerlink" href="#where-will-the-file-upload" title="Permanent link">&para;</a></h2>
<p>The AutoConnect built-in upload handler can save the upload file to three locations:</p>
<ol>
<li>Flash memory embedded in the ESP8266/ESP32 module</li>
<li>SD device externally connected to the ESP8266/ESP32 module</li>
<li>Other character devices</li>
</ol>
<p>You can specify the device type to save with the <a href="acelements.html#store"><strong>store</strong></a> attribute of AutoConnectFile, and it accepts the following values:</p>
<ul>
<li>Flash : <code>AC_File_FS</code> for the API parameter or <code>fs</code> for the JSON document</li>
<li>SD : <code>AC_File_SD</code> for the API parameter or <code>sd</code> for the JSON document</li>
<li>Other : <code>AC_File_Extern</code> for the API parameter or <code>extern</code> for the JSON document</li>
</ul>
<p>The substance of AC_File_FS (fs) is a SPIFFS file system implemented by the ESP8266/ESP32 core, and then AutoConnect uses the Global Instance <strong>SPIFFS</strong> to access SPIFFS.</p>
<p>Also, the substance of AC_File_SD (sd) is a FAT file of Arduino SD library ported to the ESP8266/ESP32 core, and then AutoConnect uses the Global Instance <strong>SD</strong> to access SD. When saving to an external SD device, there are additional required parameters for the connection interface and is defined as the macro in AutoConnectDefs.h.</p>
<div class="highlight" style="background: #272822"><pre style="line-height: 125%;"><span></span><code><span style="color: #75715e">#define AUTOCONNECT_SD_CS       SS</span>
<span style="color: #75715e">#define AUTOCONNECT_SD_SPEED    4000000</span>
</code></pre></div>
<p><code>AUTOCONNECT_SD_CS</code> defines which GPIO for the CS (Chip Select, or SS as Slave Select) pin. This definition is derived from pins_arduino.h, which is included in the Arduino core distribution. If you want to assign the CS pin to another GPIO, you need to change the macro definition of AutoConnectDefs.h.</p>
<p><code>AUTOCONNECT_SD_SPEED</code> defines SPI clock speed depending on the connected device.</p>
<div class="admonition info">
<p class="admonition-title">Involves both the begin() and the end()</p>
<p>The built-in uploader executes the begin and end functions regardless of the Sketch whence the file system of the device will terminate with the uploader termination. Therefore, to use the device in the Sketch after uploading, you need to <strong>restart it with the begin</strong> function.</p>
</div>
<h2 id="when-it-will-be-uploaded">When it will be uploaded<a class="headerlink" href="#when-it-will-be-uploaded" title="Permanent link">&para;</a></h2>
<p>Upload handler will be launched by ESP8266WebServer/WebServer(as ESP32) library which is triggered by receiving an HTTP stream of POST BODY including file content. Its launching occurs before invoking the page handler.</p>
<p>The following diagram illustrates the file uploading sequence:</p>
<p><img src="images/ac_upload_flow.svg"></p>
<p>At the time of the page handler behaves, the uploaded file already saved to the device, and the <a href="acelements.html#name_3">member variables</a> of AutoConnectFile reflects the file name and transfer size.</p>
<h2 id="the-file-name-for-the-uploaded-file">The file name for the uploaded file<a class="headerlink" href="#the-file-name-for-the-uploaded-file" title="Permanent link">&para;</a></h2>
<p>AutoConnetFile saves the uploaded file with the file name you selected by <code>&lt;input type="file"&gt;</code> tag on the browser. The file name used for uploading is stored in the AutoConnetFile's value member, which you can access after uploading. (i.e. In the handler of the destination page by the AutoConnectSubmit element.) You can not save it with a different name. It can be renamed after upload if you need to change the name.</p>
<h2 id="upload-to-a-device-other-than-flash-or-sd">Upload to a device other than Flash or SD<a class="headerlink" href="#upload-to-a-device-other-than-flash-or-sd" title="Permanent link">&para;</a></h2>
<p>You can output the file to any device using a custom uploader by specifying <a href="acjson.html#acfile"><strong>extern</strong></a> with the <a href="acjson.html#acfile"><strong>store</strong></a> attribute of <a href="acjson.html#acfile">AutoConnectFile</a> (or specifying <a href="acelements.html#store"><strong>AC_File_Extern</strong></a> for the <a href="apielements.html#store"><strong>store</strong></a> member variable) and can customize the uploader according to the need to upload files to other than Flash or SD. Implements your own uploader with inheriting the <a href="#upload-handler-base-class"><strong>AutoConnectUploadHandler</strong></a> class which is the base class of the upload handler.</p>
<div class="admonition note">
<p class="admonition-title">It's not so difficult</p>
<p>Implementing the custom uploader requires a little knowledge of the c++ language. If you are less attuned to programming c++, you may find it difficult. But don't worry. You can make it in various situations by just modifying the Sketch skeleton that appears at the end of this page.</p>
</div>
<h3 id="upload-handler-base-class"><i class="fa fa-code"></i> Upload handler base class<a class="headerlink" href="#upload-handler-base-class" title="Permanent link">&para;</a></h3>
<p>AutoConnectUploadHandler is a base class of upload handler and It has one public member function and three protected functions. </p>
<h4 id="constructor"><i class="fa fa-caret-right"></i> Constructor<a class="headerlink" href="#constructor" title="Permanent link">&para;</a></h4>
<div class="highlight" style="background: #272822"><pre style="line-height: 125%;"><span></span><code><span style="color: #f8f8f2">AutoConnectUploadHandler()</span>
</code></pre></div>
<h4 id="member-functions"><i class="fa fa-caret-right"></i> Member functions<a class="headerlink" href="#member-functions" title="Permanent link">&para;</a></h4>
<p>The <strong>upload</strong> public function is an entry point, the ESP8266WebServer (WebServer as ESP32) library will invoke the upload with each time of uploading content divided into chunks. </p>
<p>Also, the <strong>_open</strong>, <strong>_write</strong> and <strong>_close</strong> protected functions are actually responsible for saving files and are declared as pure virtual functions. A custom uploader class that inherits from the AutoConnectUploadHandler class need to implement these functions.</p>
<p>The actual upload process is handled by the three private functions above, and then upload only invokes three functions according to the upload situation. In usually, there is no need to override the upload function in an inherited class.</p>
<div class="highlight" style="background: #272822"><pre style="line-height: 125%;"><span></span><code><span style="color: #66d9ef">public</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">virtual</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2"> upload(</span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> String</span><span style="color: #f92672">&amp;</span><span style="color: #f8f8f2"> requestUri, </span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> HTTPUpload</span><span style="color: #f92672">&amp;</span><span style="color: #f8f8f2"> upload)</span>
</code></pre></div>
<dl class="apidl">
    <dt><strong>Parameters</strong></dt>
    <dd><span class="apidef">requestUri</span><span class="apidesc">URI of upload request source.</span></dd>
    <dd><span class="apidef">upload</span><span class="apidesc">A data structure of the upload file as <b>HTTPUpload</b>. It is defined in the ESP8266WebServer (WebServer as ESP32) library as follows:

<div class="highlight" style="background: #272822"><pre style="line-height: 125%;"><span></span><code><span style="color: #66d9ef">typedef</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">struct</span><span style="color: #f8f8f2"> {</span>
<span style="color: #f8f8f2">  HTTPUploadStatus status;</span>
<span style="color: #f8f8f2">  String  filename;</span>
<span style="color: #f8f8f2">  String  name;</span>
<span style="color: #f8f8f2">  String  type;</span>
<span style="color: #f8f8f2">  </span><span style="color: #66d9ef">size_t</span><span style="color: #f8f8f2">  totalSize;</span>
<span style="color: #f8f8f2">  </span><span style="color: #66d9ef">size_t</span><span style="color: #f8f8f2">  currentSize;</span>
<span style="color: #f8f8f2">  </span><span style="color: #66d9ef">size_t</span><span style="color: #f8f8f2">  contentLength;</span>
<span style="color: #f8f8f2">  </span><span style="color: #66d9ef">uint8_t</span><span style="color: #f8f8f2"> buf[HTTP_UPLOAD_BUFLEN];</span>
<span style="color: #f8f8f2">} HTTPUpload;</span>
</code></pre></div>
    </span></dd>
</dl>

<p>An upload handler needs to implement a procedure corresponding with <strong>HTTPUploadStatus</strong> enum value indicated by the uploading process of ESP8266WebServer class, which contained in HTTPUpload.status as following values:</p>
<ul>
<li><strong><code>UPLOAD_FILE_START</code></strong> : Invokes to the _open.</li>
<li><strong><code>UPLOAD_FILE_WRITE</code></strong> : Invokes to the _write.</li>
<li><strong><code>UPLOAD_FILE_END</code></strong> : Invokes to the _close.</li>
<li><strong><code>UPLOAD_FILE_ABORTED</code></strong> : Invokes to the _close.</li>
</ul>
<p>The _open function will be invoked when HTTPUploadStatus is <strong>UPLOAD_FILE_START</strong>. Usually, the implementation of an inherited class will open the file.</p>
<div class="highlight" style="background: #272822"><pre style="line-height: 125%;"><span></span><code><span style="color: #66d9ef">protected</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">virtual</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">bool</span><span style="color: #f8f8f2"> _open(</span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">char</span><span style="color: #f92672">*</span><span style="color: #f8f8f2"> filename, </span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">char</span><span style="color: #f92672">*</span><span style="color: #f8f8f2"> mode) </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> </span><span style="color: #ae81ff">0</span>
</code></pre></div>
<dl class="apidl">
    <dt><strong>Parameters</strong></dt>
    <dd><span class="apidef">filename</span><span class="apidesc">Uploading file name.</span></dd>
    <dd><span class="apidef">mode</span><span class="apidesc">An indicator for the file access mode, a "w" for writing.</span></dd>
    <dt><strong>Return value</strong></dt>
    <dd><span class="apidef">true</span><span class="apidesc">File open successful.</span></dd>
    <dd><span class="apidef">false</span><span class="apidesc">Failed to open.</span></dd>
</dl>

<p>The _write function will be invoked when HTTPUploadStatus is <strong>UPLOAD_FILE_WRITE</strong>. The content of the upload file is divided and the _write will be invoked in multiple times. Usually, the implementation of an inherited class will write data.</p>
<div class="highlight" style="background: #272822"><pre style="line-height: 125%;"><span></span><code><span style="color: #66d9ef">protected</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">virtual</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">size_t</span><span style="color: #f8f8f2"> _write(</span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">uint8_t</span><span style="color: #f8f8f2"> </span><span style="color: #f92672">*</span><span style="color: #f8f8f2">buf, </span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">size_t</span><span style="color: #f8f8f2"> size) </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> </span><span style="color: #ae81ff">0</span>
</code></pre></div>
<dl class="apidl">
    <dt><strong>Parameters</strong></dt>
    <dd><span class="apidef">buf</span><span class="apidesc">File content block.</span></dd>
    <dd><span class="apidef">size</span><span class="apidesc">File block size to write.</span></dd>
    <dt><strong>Return value</strong></dt>
    <dd>Size written.</dd>
</dl>

<p>The _close function will be invoked when HTTPUploadStatus is <strong>UPLOAD_FILE_END</strong> or <strong>UPLOAD_FILE_ABORTED</strong>. Usually, the implementation of an inherited class will close the file.</p>
<div class="highlight" style="background: #272822"><pre style="line-height: 125%;"><span></span><code><span style="color: #66d9ef">protected</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">virtual</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2"> _close(</span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2">) </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> </span><span style="color: #ae81ff">0</span>
</code></pre></div>
<p>For reference, the following AutoConnectUploadFS class is an implementation of AutoConnect built-in uploader and inherits from AutoConnectUploadHandler.</p>
<div class="highlight" style="background: #272822"><pre style="line-height: 125%;"><span></span><code><span style="color: #66d9ef">class</span><span style="color: #f8f8f2"> </span><span style="color: #a6e22e">AutoConnectUploadFS</span><span style="color: #f8f8f2"> </span><span style="color: #f92672">:</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">public</span><span style="color: #f8f8f2"> AutoConnectUploadHandler {</span>
<span style="color: #f8f8f2"> </span><span style="color: #66d9ef">public</span><span style="color: #f92672">:</span>
<span style="color: #f8f8f2">  </span><span style="color: #66d9ef">explicit</span><span style="color: #f8f8f2"> AutoConnectUploadFS(SPIFFST</span><span style="color: #f92672">&amp;</span><span style="color: #f8f8f2"> media) </span><span style="color: #f92672">:</span><span style="color: #f8f8f2"> _media(</span><span style="color: #f92672">&amp;</span><span style="color: #f8f8f2">media) {}</span>
<span style="color: #f8f8f2">  </span><span style="color: #f92672">~</span><span style="color: #f8f8f2">AutoConnectUploadFS() { _close(); }</span>

<span style="color: #f8f8f2"> </span><span style="color: #66d9ef">protected</span><span style="color: #f92672">:</span>
<span style="color: #f8f8f2">  </span><span style="color: #66d9ef">bool</span><span style="color: #f8f8f2"> _open(</span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">char</span><span style="color: #f92672">*</span><span style="color: #f8f8f2"> filename, </span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">char</span><span style="color: #f92672">*</span><span style="color: #f8f8f2"> mode) </span><span style="color: #66d9ef">override</span><span style="color: #f8f8f2"> {</span>
<span style="color: #f8f8f2">    </span><span style="color: #66d9ef">if</span><span style="color: #f8f8f2"> (_media</span><span style="color: #f92672">-&gt;</span><span style="color: #f8f8f2">begin()) {</span>
<span style="color: #f8f8f2">      _file </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> _media</span><span style="color: #f92672">-&gt;</span><span style="color: #f8f8f2">open(filename, mode);</span>
<span style="color: #f8f8f2">      </span><span style="color: #66d9ef">return</span><span style="color: #f8f8f2"> _file </span><span style="color: #f92672">!=</span><span style="color: #f8f8f2"> false;      </span>
<span style="color: #f8f8f2">    }</span>
<span style="color: #f8f8f2">    </span><span style="color: #66d9ef">return</span><span style="color: #f8f8f2"> false;</span>
<span style="color: #f8f8f2">  }</span>

<span style="color: #f8f8f2">  </span><span style="color: #66d9ef">size_t</span><span style="color: #f8f8f2"> _write(</span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">uint8_t</span><span style="color: #f92672">*</span><span style="color: #f8f8f2"> buf, </span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">size_t</span><span style="color: #f8f8f2"> size) </span><span style="color: #66d9ef">override</span><span style="color: #f8f8f2"> {</span>
<span style="color: #f8f8f2">    </span><span style="color: #66d9ef">if</span><span style="color: #f8f8f2"> (_file)</span>
<span style="color: #f8f8f2">      </span><span style="color: #66d9ef">return</span><span style="color: #f8f8f2"> _file.write(buf, size);</span>
<span style="color: #f8f8f2">    </span><span style="color: #66d9ef">else</span>
<span style="color: #f8f8f2">      </span><span style="color: #66d9ef">return</span><span style="color: #f8f8f2"> </span><span style="color: #ae81ff">-1</span><span style="color: #f8f8f2">;</span>
<span style="color: #f8f8f2">  }</span>

<span style="color: #f8f8f2">  </span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2"> _close(</span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2">) </span><span style="color: #66d9ef">override</span><span style="color: #f8f8f2"> {</span>
<span style="color: #f8f8f2">    </span><span style="color: #66d9ef">if</span><span style="color: #f8f8f2"> (_file)</span>
<span style="color: #f8f8f2">      _file.close();</span>
<span style="color: #f8f8f2">    _media</span><span style="color: #f92672">-&gt;</span><span style="color: #f8f8f2">end();</span>
<span style="color: #f8f8f2">  }</span>

<span style="color: #f8f8f2"> </span><span style="color: #66d9ef">private</span><span style="color: #f92672">:</span>
<span style="color: #f8f8f2">  SPIFFST</span><span style="color: #f92672">*</span><span style="color: #f8f8f2">  _media;</span>
<span style="color: #f8f8f2">  SPIFileT  _file; </span>
<span style="color: #f8f8f2">};</span>
</code></pre></div>
<h3 id="register-custom-upload-handler"><i class="fa fa-code"></i> Register custom upload handler<a class="headerlink" href="#register-custom-upload-handler" title="Permanent link">&para;</a></h3>
<p>In order to upload a file by the custom uploader, it is necessary to register it to the custom Web page beforehand. To register a custom uploader, specify the custom uploader class name in the template argument of the  <a href="apiaux.html#onupload">AutoConnectAux::onUpload</a> function and invokes it.</p>
<div class="highlight" style="background: #272822"><pre style="line-height: 125%;"><span></span><code><span style="color: #66d9ef">void</span><span style="color: #f8f8f2"> AutoConnectAux</span><span style="color: #f92672">::</span><span style="color: #f8f8f2">onUpload</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">T</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(T</span><span style="color: #f92672">&amp;</span><span style="color: #f8f8f2"> uploadClass)</span>
</code></pre></div>
<dl class="apidl">
    <dt><strong>Parameters</strong></dt>
    <dd><span class="apidef">T</span><span class="apidesc">Specifies a class name of the custom uploader. This class name is a class that you implemented by inheriting AutoConnectUploadHandler for custom upload.</span></dd>
    <dd><span class="apidef">uploadClass</span><span class="apidesc">Specifies the custom upload class instance.</span></dd>
</dl>

<p>The rough structure of the Sketches that completed these implementations will be as follows:</p>
<div class="highlight" style="background: #272822"><pre style="line-height: 125%;"><span></span><code><span style="color: #75715e">#include</span><span style="color: #f8f8f2"> </span><span style="color: #75715e">&lt;ESP8266WiFi.h&gt;</span>
<span style="color: #75715e">#include</span><span style="color: #f8f8f2"> </span><span style="color: #75715e">&lt;ESP8266WebServer.h&gt;</span>
<span style="color: #75715e">#include</span><span style="color: #f8f8f2"> </span><span style="color: #75715e">&lt;AutoConnect.h&gt;</span>

<span style="color: #66d9ef">static</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">char</span><span style="color: #f8f8f2"> PAGE_UPLOAD[] PROGMEM </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> </span><span style="color: #e6db74">R&quot;(</span>
<span style="color: #e6db74">{</span>
<span style="color: #e6db74">  &quot;uri&quot;: &quot;/&quot;,</span>
<span style="color: #e6db74">  &quot;title&quot;: &quot;Upload&quot;,</span>
<span style="color: #e6db74">  &quot;menu&quot;: true,</span>
<span style="color: #e6db74">  &quot;element&quot;: [</span>
<span style="color: #e6db74">    { &quot;name&quot;:&quot;caption&quot;, &quot;type&quot;:&quot;ACText&quot;, &quot;value&quot;:&quot;&lt;h2&gt;File uploading platform&lt;h2&gt;&quot; },</span>
<span style="color: #e6db74">    { &quot;name&quot;:&quot;upload_file&quot;, &quot;type&quot;:&quot;ACFile&quot;, &quot;label&quot;:&quot;Select file: &quot;, &quot;store&quot;:&quot;extern&quot; },</span>
<span style="color: #e6db74">    { &quot;name&quot;:&quot;upload&quot;, &quot;type&quot;:&quot;ACSubmit&quot;, &quot;value&quot;:&quot;UPLOAD&quot;, &quot;uri&quot;:&quot;/upload&quot; }</span>
<span style="color: #e6db74">  ]</span>
<span style="color: #e6db74">}</span>
<span style="color: #e6db74">)&quot;</span><span style="color: #f8f8f2">;</span>

<span style="color: #66d9ef">static</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">char</span><span style="color: #f8f8f2"> PAGE_RECEIVED[] PROGMEM </span><span style="color: #f92672">=</span><span style="color: #f8f8f2"> </span><span style="color: #e6db74">R&quot;(</span>
<span style="color: #e6db74">{</span>
<span style="color: #e6db74">  &quot;uri&quot;: &quot;/upload&quot;,</span>
<span style="color: #e6db74">  &quot;title&quot;: &quot;Upload ended&quot;,</span>
<span style="color: #e6db74">  &quot;menu&quot;: false,</span>
<span style="color: #e6db74">  &quot;element&quot;: [</span>
<span style="color: #e6db74">    { &quot;name&quot;:&quot;caption&quot;, &quot;type&quot;:&quot;ACText&quot;, &quot;value&quot;:&quot;&lt;h2&gt;File uploading ended&lt;h2&gt;&quot; }</span>
<span style="color: #e6db74">  ]</span>
<span style="color: #e6db74">}</span>
<span style="color: #e6db74">)&quot;</span><span style="color: #f8f8f2">;</span>

<span style="color: #75715e">// Custom upload handler class</span>
<span style="color: #66d9ef">class</span><span style="color: #f8f8f2"> </span><span style="color: #a6e22e">CustomUploader</span><span style="color: #f8f8f2"> </span><span style="color: #f92672">:</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">public</span><span style="color: #f8f8f2"> AutoConnectUploadHandler {</span>
<span style="color: #66d9ef">public</span><span style="color: #f92672">:</span>
<span style="color: #f8f8f2">  CustomUploader() {}</span>
<span style="color: #f8f8f2">  </span><span style="color: #f92672">~</span><span style="color: #f8f8f2">CustomUploader() {}</span>

<span style="color: #66d9ef">protected</span><span style="color: #f92672">:</span>
<span style="color: #f8f8f2">  </span><span style="color: #66d9ef">bool</span><span style="color: #f8f8f2">   _open(</span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">char</span><span style="color: #f92672">*</span><span style="color: #f8f8f2"> filename, </span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">char</span><span style="color: #f92672">*</span><span style="color: #f8f8f2"> mode) </span><span style="color: #66d9ef">override</span><span style="color: #f8f8f2">;</span>
<span style="color: #f8f8f2">  </span><span style="color: #66d9ef">size_t</span><span style="color: #f8f8f2"> </span><span style="color: #a6e22e">_write</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">uint8_t</span><span style="color: #f8f8f2"> </span><span style="color: #f92672">*</span><span style="color: #f8f8f2">buf, </span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">size_t</span><span style="color: #f8f8f2"> size) </span><span style="color: #66d9ef">override</span><span style="color: #f8f8f2">;</span>
<span style="color: #f8f8f2">  </span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2">   </span><span style="color: #a6e22e">_close</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2">) </span><span style="color: #66d9ef">override</span><span style="color: #f8f8f2">;</span>
<span style="color: #f8f8f2">};</span>

<span style="color: #75715e">// _open for custom open</span>
<span style="color: #66d9ef">bool</span><span style="color: #f8f8f2"> </span><span style="color: #a6e22e">CustomUploader::_open</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">char</span><span style="color: #f92672">*</span><span style="color: #f8f8f2"> filename, </span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">char</span><span style="color: #f92672">*</span><span style="color: #f8f8f2"> mode) {</span>
<span style="color: #f8f8f2">  </span><span style="color: #75715e">// Here, an implementation for the open file.</span>
<span style="color: #f8f8f2">}</span>

<span style="color: #75715e">// _open for custom write</span>
<span style="color: #66d9ef">size_t</span><span style="color: #f8f8f2"> </span><span style="color: #a6e22e">CustomUploader::_write</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">uint8_t</span><span style="color: #f8f8f2"> </span><span style="color: #f92672">*</span><span style="color: #f8f8f2">buf, </span><span style="color: #66d9ef">const</span><span style="color: #f8f8f2"> </span><span style="color: #66d9ef">size_t</span><span style="color: #f8f8f2"> size) {</span>
<span style="color: #f8f8f2">  </span><span style="color: #75715e">// Here, an implementation for the writing the file data.</span>
<span style="color: #f8f8f2">}</span>

<span style="color: #75715e">// _open for custom close</span>
<span style="color: #66d9ef">void</span><span style="color: #f8f8f2"> </span><span style="color: #a6e22e">CustomUploader::_close</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">void</span><span style="color: #f8f8f2">) {</span>
<span style="color: #f8f8f2">  </span><span style="color: #75715e">// Here, an implementation for the close file.</span>
<span style="color: #f8f8f2">}</span>

<span style="color: #f8f8f2">AutoConnect     portal;</span>
<span style="color: #f8f8f2">AutoConnectAux  uploadPage;</span>
<span style="color: #f8f8f2">AutoConnectAux  receivePage;</span>
<span style="color: #f8f8f2">CustomUploader  uploader;   </span><span style="color: #75715e">// Declare the custom uploader</span>

<span style="color: #66d9ef">void</span><span style="color: #f8f8f2"> </span><span style="color: #a6e22e">setup</span><span style="color: #f8f8f2">() {</span>
<span style="color: #f8f8f2">  uploadPage.load(PAGE_UPLOAD);</span>
<span style="color: #f8f8f2">  receivePage.load(PAGE_RECEIVED);</span>
<span style="color: #f8f8f2">  portal.join({ uploadPage, receivePage });</span>
<span style="color: #f8f8f2">  receivePage.onUpload</span><span style="color: #f92672">&lt;</span><span style="color: #f8f8f2">CustomUploader</span><span style="color: #f92672">&gt;</span><span style="color: #f8f8f2">(uploader);  </span><span style="color: #75715e">// Register the custom uploader</span>
<span style="color: #f8f8f2">  portal.begin();</span>
<span style="color: #f8f8f2">}</span>

<span style="color: #66d9ef">void</span><span style="color: #f8f8f2"> </span><span style="color: #a6e22e">loop</span><span style="color: #f8f8f2">() {</span>
<span style="color: #f8f8f2">  portal.handleClient();</span>
<span style="color: #f8f8f2">}</span>
</code></pre></div>
<div class="admonition note">
<p class="admonition-title">Don't forget to specify the store</p>
<p>When using a custom uploader, remember to specify the <strong>extern</strong> for the store attribute of AutoConnectFile.</p>
</div>
<script>
  window.onload = function() {
    Gifffer();
  };
</script>

<div class="footnote">
<hr />
<ol>
<li id="fn:1">
<p>The AutoConnectFile element can be used with other AutoConnectElements on the same page.&#160;<a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text">&#8617;</a></p>
</li>
</ol>
</div>


  




                
              </article>
            </div>
          
          
        </div>
        
          <a href="#" class="md-top md-icon" data-md-component="top" hidden>
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12Z"/></svg>
            Back to top
          </a>
        
      </main>
      
        <footer class="md-footer">
  
  <div class="md-footer-meta md-typeset">
    <div class="md-footer-meta__inner md-grid">
      <div class="md-copyright">
  
    <div class="md-copyright__highlight">
      Copyright &copy; 2018-2023 Hieromon Ikasamo
    </div>
  
  
    Made with
    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
      Material for MkDocs
    </a>
  
</div>
      
        <div class="md-social">
  
    
    
      
      
    
    <a href="https://github.com/Hieromon" target="_blank" rel="noopener" title="github.com" class="md-social__link">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
    </a>
  
    
    
      
      
    
    <a href="https://twitter.com/hieromon" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>
    </a>
  
</div>
      
    </div>
  </div>
</footer>
      
    </div>
    <div class="md-dialog" data-md-component="dialog">
      <div class="md-dialog__inner md-typeset"></div>
    </div>
    
    <script id="__config" type="application/json">{"base": ".", "features": ["navigation.top"], "search": "assets/javascripts/workers/search.db81ec45.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
    
    
      <script src="assets/javascripts/bundle.a00a7c5e.min.js"></script>
      
        <script src="js/gifffer.min.js"></script>
      
    
  </body>
</html>